package com.culture.config.common.filter;

import java.io.IOException;
import java.util.Enumeration;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.culture.config.common.util.HostAddressUtil;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
@WebFilter
@Order(value=1)
public class LogFilter implements Filter {  

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException { 
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String requestURI = httpServletRequest.getRequestURI();
    	if(checkIsIgnore(requestURI)) {
    		 chain.doFilter(request, response);
    		 return;
    	} 
        FilterRequestWrapper filterRequestWrapper = new FilterRequestWrapper(httpServletRequest);
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        FilterResponseWrapper filterResponseWrapper = new FilterResponseWrapper(httpServletResponse);
        UUID guid = UUID.randomUUID();
        log.info("====>request Id:{}, client:{}, path:{}, header:[{}], data:[{}]",
            guid,    
            HostAddressUtil.getClientIpAddress(httpServletRequest),               
            filterRequestWrapper.getRequestURI(),
            this.logHeader(httpServletRequest),
            new String(filterRequestWrapper.getBody(),filterRequestWrapper.getCharacterEncoding()));  
        chain.doFilter(filterRequestWrapper, filterResponseWrapper);     
        byte[] responseData = filterResponseWrapper.getResponseData();  
        log.info("<====response Id:{},data:{}",guid, new String(responseData, response.getCharacterEncoding()));   
        ServletOutputStream output = response.getOutputStream();
        output.write(responseData);
        output.flush();           
    }    
    
    private boolean checkIsIgnore(String requestURI) {
    	if(StringUtils.isBlank(requestURI)) {
    		return false;
    	}
    	String [] searchChars = new String[] {"/swagger",
    			"/javascript/",
    			"/framepages/",
    			"/datapages/",
    			"/stylesheets/",
    			"login.html",
    			"default.html"};    			
    	return StringUtils.containsAny(requestURI, searchChars);  
    }

    private String logHeader(HttpServletRequest httpServletRequest){
        Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
        if(Objects.isNull(headerNames)){
            return null;
        }
        StringBuilder sb = new StringBuilder();
        while(headerNames.hasMoreElements()){
            String name = headerNames.nextElement();
            sb.append(name);
            sb.append("=");
            sb.append(httpServletRequest.getHeader(name));
            sb.append(",");
        }
        return sb.toString();
    }
}